"""
__author__ = 'loong'
"""
from baye import models
from baye import structures
from baye.util import ET, dec_raise_xml
from baye.condition import Condition
from baye import resid


class Person:
    @classmethod
    def nil(cls, period):
        return Person(period, -1)

    class meta:
        tag = '人物'
        name = '名称'
        belong = '归属'
        level = '等级'
        force = '武力'
        iq = '智力'
        devotion = '忠诚'
        character = '性格'
        exp = '经验'
        thew = '体力'
        arm_type = '兵种'
        arms = '兵力'
        equip0 = '道具1'
        equip1 = '道具2'
        age = '年龄'
        skill = '专长'

        adult_year = '成年'
        birth_city = '出生地'
        bole = '伯乐'

    def __init__(self, period, index):
        self.period = period
        self.index = index
        self.name = ''
        self.belong = 0
        self.level = 0
        self.force = 0
        self.iq = 0
        self.devotion = 0
        self.character = 0
        self.exp = 0
        self.thew = 0
        self.arm_type = 0
        self.arms = 0
        self.equip0 = 0
        self.equip1 = 0
        self.age = 0
        self.skill = 0
        self.condition = Condition()

    def load_bin(self, data):
        info = structures.read_struct(data, 0, models.PERSON)
        self.__dict__.update(info)
        self.load_condition_from_bin()
        return self

    def get_condition_from_bin(self):
        size = structures.sizeof(models.CONDITION)
        data = self.period.lib.resources[resid.GENERAL_CON].items[self.period.index]
        condition = Condition()
        condition.load_bin(data[self.index*size:])
        return condition

    def load_condition_from_bin(self):
        self.condition = self.get_condition_from_bin()

    def bin(self):
        data = {'id': self.index + 1}
        data.update(self.__dict__)
        return structures.write_struct(data, models.PERSON)

    def link(self):
        period = self.period
        if self.belong:
            self.belong = period.people[self.belong-1].name
        else:
            self.belong = ''
        self.arm_type = period.lib.arm_types[self.arm_type].name

        def get_tool(idx):
            if 0 <= idx < len(period.lib.tools):
                return period.lib.tools[idx].name
            return ''
        self.equip0 = get_tool(self.equip0-1)
        self.equip1 = get_tool(self.equip1-1)
        self.link_condition()

    def link_condition(self):
        if self.condition is not None:
            condition = self.condition
            if condition.bole:
                condition.bole = self.period.people[condition.bole-1].name
            else:
                condition.bole = ''
            if condition.city:
                condition.city = self.period.lib.cities[condition.city-1].name
            else:
                condition.city = ''

    def unlink(self):
        period = self.period
        self.belong = period.get_person_by_name(self.belong) + 1
        self.arm_type = period.lib.get_arm_type_by_name(self.arm_type).index

        def get_tool_id(name):
            if name:
                return period.lib.get_tool_by_name(name).index + 1
            else:
                return 0

        self.equip0 = get_tool_id(self.equip0)
        self.equip1 = get_tool_id(self.equip1)
        self.unlink_condition()

    def unlink_condition(self):
        if self.condition is not None:
            condition = self.condition
            condition.bole = self.period.get_person_by_name(condition.bole) + 1
            condition.city = self.period.lib.get_city_index_by_name(condition.city) + 1

    def xml(self):
        p = ET.Element(self.meta.tag)
        attrs = {}
        attrs[self.meta.name] = self.name
        attrs[self.meta.belong] = self.belong
        attrs[self.meta.level] = self.level
        attrs[self.meta.force] = self.force
        attrs[self.meta.iq] = self.iq
        attrs[self.meta.devotion] = self.devotion
        attrs[self.meta.character] = self.character
        attrs[self.meta.arm_type] = self.arm_type
        attrs[self.meta.equip0] = self.equip0
        attrs[self.meta.equip1] = self.equip1
        attrs[self.meta.age] = self.age

        if self.condition is not None:
            condition = self.condition
            attrs[self.meta.adult_year] = condition.birth and condition.birth + 16 or ''
            attrs[self.meta.birth_city] = condition.city
            attrs[self.meta.bole] = condition.bole

        if self.skill:
            skill_name = self.period.lib.skills[self.skill-1].name
        else:
            skill_name = ''
        attrs[self.meta.skill] = skill_name

        p.attrib = {k: str(v) for k, v in attrs.items()}

        return p

    @dec_raise_xml
    def load_xml(self, xml):
        self.name = xml.attrib[self.meta.name]
        self.belong = xml.attrib[self.meta.belong]
        self.level = int(xml.attrib[self.meta.level])
        self.force = int(xml.attrib[self.meta.force])
        self.iq = int(xml.attrib[self.meta.iq])
        self.devotion = int(xml.attrib[self.meta.devotion])
        self.character = int(xml.attrib[self.meta.character])
        self.arm_type = xml.attrib[self.meta.arm_type]
        self.equip0 = xml.attrib[self.meta.equip0]
        self.equip1 = xml.attrib[self.meta.equip1]
        self.age = int(xml.attrib[self.meta.age])

        self.skill = self.period.lib.get_skill_index_by_name(xml.attrib[self.meta.skill]) + 1
        self.load_condition_from_xml(xml)

    def load_condition_from_xml(self, xml):
        condition = Condition()
        grown = int(xml.attrib[self.meta.adult_year] or 0)
        condition.birth = grown and grown - 16
        condition.city = xml.attrib[self.meta.birth_city]
        condition.bole = xml.attrib[self.meta.bole]
        self.condition = condition
